package com.futvan.z.framework.util;

import java.security.MessageDigest;
import java.security.Security;
import java.util.Arrays;
import java.util.HashMap;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

import com.alibaba.fastjson.JSONObject;
import com.futvan.z.framework.common.bean.Code;
import com.futvan.z.framework.common.bean.Result;
import com.futvan.z.framework.core.z;
import com.futvan.z.system.zweixinmessages.z_weixin_messages;
import com.qq.weixin.mp.aes.WXBizMsgCrypt;

import sun.misc.BASE64Decoder;

/**
 * 微信工具类
 * @author 4223947@qq.com
 *
 */
public class WeiXinUtil {
	
	/**
	 * 微信请求转为对象
	 * @param xml
	 * @return
	 */
	public static z_weixin_messages XmlToInfo(String xml){
		z_weixin_messages x_wechat = null;
		HashMap<String,java.lang.Class> cs = new HashMap<String, Class>();
		cs.put("xml", z_weixin_messages.class);
		x_wechat = (z_weixin_messages) XmlUtil.XmlToObject(xml,cs);
		return x_wechat;
	}

	/**
	 * 返回对象转为XML
	 * @param x_wechat
	 * @return
	 */
	public static String InfoToXML(z_weixin_messages x_wechat){
		HashMap<String,java.lang.Class> cs = new HashMap<String, Class>();
		cs.put("xml", z_weixin_messages.class);
//		cs.put("item", item.class);
		return XmlUtil.ObjectToXml(x_wechat,cs);
	}
	
	
	/**
	 * 消息解密
	 * @param msg
	 * @return
	 */
	public static String Decrypt(String msg,String msgSignature,String timestamp,String nonce){
		String r = null;
		try {
			if(!"".equals(msg) && msg!=null){
				WXBizMsgCrypt pc = new WXBizMsgCrypt(z.sp.get("weixin_token"), z.sp.get("weixin_EncodingAESKey"), z.sp.get("weixin_appid"));
				r = pc.decryptMsg(msgSignature, timestamp, nonce, msg);
			}
		} catch (Exception e) {
			z.Error("微信消息解密出错", e);
		}
		return r;
	}

	/**
	 * 消息加密
	 * @param msg
	 * @return
	 * @throws Exception 
	 */
	public static String Encryption(String msg,String timestamp,String nonce){
		String r = null;
		try {
			if(!"".equals(msg) && msg!=null){
				WXBizMsgCrypt pc = new WXBizMsgCrypt(z.sp.get("weixin_token"), z.sp.get("weixin_EncodingAESKey"), z.sp.get("weixin_appid"));
				r = pc.encryptMsg(msg, timestamp, nonce);
			}
		} catch (Exception e) {
			z.Error("微信消息加密出错", e);
		}
		return r;
	}
	
	/**
	 * 微信通信接口验证
	 * @param signature 微信加密签名，signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
	 * @param timestamp 时间戳
	 * @param nonce 随机数
	 * @return boolean
	 */
	public static boolean CheckingInfo(String signature, String timestamp,String nonce) {
		boolean returnvalue = false;
		String weixin_token = z.sp.get("weixin_token");
		if (z.isNotNull(signature) && z.isNotNull(timestamp) && z.isNotNull(nonce) && z.isNotNull(weixin_token)) {
			//封装参数
			String[] ArrTmp = {weixin_token, timestamp, nonce };
			Arrays.sort(ArrTmp);
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < ArrTmp.length; i++) {
				sb.append(ArrTmp[i]);
			}
			//生成加密签名
			String pwd = encipher(sb.toString());
			//比对签名
			if (signature.equals(pwd)) {
				returnvalue = true;
			} else {
				z.Error("微信通信接口验证失败，比对签名失败|生成签名："+pwd+"|signature："+signature+"|timestamp:"+timestamp+"|nonce:"+nonce+"|weixin_token:"+weixin_token);
			}
		}else {
			z.Error("微信通信接口验证失败，参数缺失|signature："+signature+"|timestamp:"+timestamp+"|nonce:"+nonce+"|weixin_token:"+weixin_token);
		}
		return returnvalue;
	}
	
	/**
	 * 文本加密(SHA-1)
	 * @author:赵戬
	 * @Email:4223947@qq.com
	 * @param info
	 * @return String
	 */
	private static String encipher(String info) {
		String returnvalue = "";
		try {
			//如果是SHA加密只需要将"SHA-1"改成"SHA"即可
			MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1"); 
			digest.update(info.getBytes());
			byte messageDigest[] = digest.digest();
			// Create Hex String
			StringBuffer hexStr = new StringBuffer();
			// 字节数组转换为 十六进制 数
			for (int i = 0; i < messageDigest.length; i++) {
				String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
				if (shaHex.length() < 2) {
					hexStr.append(0);
				}
				hexStr.append(shaHex);
			}
			returnvalue = hexStr.toString();
		} catch (Exception e) {
			z.Error("微信通信接口验证|签名加密出错",e);
		}
		return returnvalue;
	}


	/**
	 * 解析encryptedData获取手机号码
	 * @param session_key
	 * @param encryptedData
	 * @param iv
	 * @return
	 */
	public static Result getUserPhoneNumber(String session_key,String encryptedData,String iv) {
		Result result = new Result();
		if(z.isNotNull(session_key)) {
			if(z.isNotNull(encryptedData)) {
				if(z.isNotNull(iv)) {
					try {
						BASE64Decoder decoder = new BASE64Decoder();
						byte[] raw = decoder.decodeBuffer(session_key);
						SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
						IvParameterSpec ivParameter = new IvParameterSpec(decoder.decodeBuffer(iv));
						Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
						cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivParameter);
						byte[] myendicod = decoder.decodeBuffer(encryptedData);
						byte[] original = cipher.doFinal(myendicod);
						String originalString = new String(original, "UTF-8");
						HashMap json = JsonUtil.getObject(originalString, HashMap.class);
						if(z.isNotNull(json) && z.isNotNull(json.get("phoneNumber"))) {
							result.setCode(Code.SUCCESS);
							result.setMsg("ok");
							result.setData(json.get("phoneNumber"));
						}else {
							result.setCode(Code.ERROR);
							result.setMsg("解析 encryptedData 出错,未找到电话号码 ");
						}
					} catch (Exception ex) {
						result.setCode(Code.ERROR);
						result.setMsg("解析 encryptedData 出错|"+ex.getMessage());
					}
				}else {
					result.setCode(Code.ERROR);
					result.setMsg("iv is null");
				}
			}else {
				result.setCode(Code.ERROR);
				result.setMsg("encryptedData is null");
			}
		}else {
			result.setCode(Code.ERROR);
			result.setMsg("session_key is null");
		}
		return result;
	}

	/**
	 * 	获取OpenId 用户唯一标识     session_key会话密钥
	 * @param appid
	 * @param secret
	 * @param js_code
	 * @return
	 */
	public static Result jscode2session(String appid,String secret,String js_code) {
		Result result = new Result();
		if(z.isNotNull(appid)) {
			if(z.isNotNull(secret)) {
				if(z.isNotNull(js_code)) {
					HashMap<String,String> parameters = new HashMap<String,String>();
					parameters.put("appid", appid);
					parameters.put("secret", secret);
					parameters.put("js_code", js_code);
					parameters.put("grant_type", "authorization_code");
					String txt = HttpUtil.doGet("https://api.weixin.qq.com/sns/jscode2session", parameters);
					if(z.isNotNull(txt)) {
						HashMap json = new HashMap();
						try {
							json = JSONObject.parseObject(txt, HashMap.class);
							if(z.isNotNull(json) && z.isNotNull(json.get("openid"))) {
								//根据OpenId获取客户zid
								String custom_zid = z.getSqlSession().selectOne("selectone", "SELECT zid FROM crm_customer WHERE wechat_openid = '"+json.get("openid")+"'");
								if(z.isNotNull(custom_zid)) {
									json.put("zid", custom_zid);
									result.setCode(Code.SUCCESS);
									result.setMsg("ok");
									result.setData(json);
								}else {
									result.setCode(Code.SUCCESS);
									result.setMsg("ok but zid is null");
									result.setData(json);
								}
							}else {
								result.setCode(Code.ERROR);
								result.setMsg("微信：jscode2session接口返回内容错误|返回值:"+txt);
							}

						} catch (Exception e) {
							result.setCode(Code.ERROR);
							result.setMsg("微信：jscode2session接口返回内容无法转换成json数据|返回值 ："+txt);
						}

					}else {
						result.setCode(Code.ERROR);
						result.setMsg("微信：jscode2session接口返回为空");
					}


				}else {
					result.setCode(Code.ERROR);
					result.setMsg("js_code is null");
				}
			}else {
				result.setCode(Code.ERROR);
				result.setMsg("secret is null");
			}
		}else {
			result.setCode(Code.ERROR);
			result.setMsg("appid is null");
		}
		return result;
	}
}
